<template>
  <div class="events-page">
    <h2 class="page-subtitle">我的比赛管理</h2>

    <div class="tabs-container">
      <div class="tabs">
        <button
          class="tab-btn"
          :class="{ active: activeTab === 'all' }"
          @click="handleTabChange('all')"
          :disabled="loadingTabs"
        >
          全部比赛
          <span v-if="loadingTabs && activeTab === 'all'" class="tab-loading"></span>
        </button>
        <button
          class="tab-btn"
          :class="{ active: activeTab === 'registered' }"
          @click="handleTabChange('registered')"
          :disabled="loadingTabs"
        >
          我已报名的比赛
          <span v-if="loadingTabs && activeTab === 'registered'" class="tab-loading"></span>
        </button>
        <!-- 新增：我的成绩标签页 -->
        <button
          class="tab-btn"
          :class="{ active: activeTab === 'scores' }"
          @click="handleTabChange('scores')"
          :disabled="loadingTabs"
        >
          我的成绩
          <span v-if="loadingTabs && activeTab === 'scores'" class="tab-loading"></span>
        </button>
      </div>

      <div class="tab-content">
        <!-- 全部比赛列表 -->
        <div v-if="activeTab === 'all'" class="tab-panel">
          <div class="filter-bar">
            <select
              v-model="selectedCategory"
              class="category-select"
              @change="fetchEvents"
              :disabled="loadingEvents"
            >
              <option value="">所有类别</option>
              <option value="田径">田径</option>
              <option value="球类">球类</option>
              <option value="游泳">游泳</option>
              <option value="武术">武术</option>
              <option value="其他">其他</option>
            </select>

            <div class="search-box">
              <input
                type="text"
                v-model="searchKeyword"
                placeholder="搜索比赛名称..."
                @keyup.enter="fetchEvents"
                :disabled="loadingEvents"
                maxlength="50"
              >
              <button
                class="search-btn"
                @click="fetchEvents"
                :disabled="loadingEvents"
              >
                <i class="icon-search" v-if="!loadingEvents">🔍</i>
                <span class="search-loading" v-if="loadingEvents"></span>
              </button>
            </div>
          </div>

          <!-- 全部比赛列表组件 -->
          <EventList
            :events="events"
            :loading="loadingEvents"
            :error="errorEvents"
            :registered-event-ids="registeredEventIds"
            @refresh="fetchEvents"
            @view-detail="handleViewEventDetail"
            @register-event="handleRegisterEvent"
          />
        </div>

        <!-- 已报名比赛列表 -->
        <div v-if="activeTab === 'registered'" class="tab-panel">
          <div class="user-registered-info">
            <h3>我的报名记录</h3>
            <p v-if="registeredEvents.length === 0" class="no-data">您还没有报名任何比赛</p>
          </div>
          <RegisteredList
            :events="registeredEvents"
            :loading="loadingRegistered"
            :error="errorRegistered"
            @refresh="fetchRegisteredEvents"
            @cancel-registration="handleCancelRegistration"
            @view-detail="handleViewEventDetail"
          />
        </div>

        <!-- 新增：我的成绩面板 -->
        <div v-if="activeTab === 'scores'" class="tab-panel">
          <div class="user-scores-info">
            <h3>我的成绩记录</h3>
            <p v-if="scores.length === 0 && !loadingScores" class="no-data">暂无成绩记录</p>
          </div>
          <MyScores
            :scores="scores"
            :loading="loadingScores"
            :error="errorScores"
            @refresh="fetchMyScores"
          />
        </div>
      </div>
    </div>

    <!-- 比赛详情弹窗 -->
    <div
      class="modal-backdrop"
      v-if="showEventDetail"
      @click.self="closeEventDetail"
    >
      <div class="modal">
        <div class="modal-header">
          <h3 class="modal-title">{{ currentEvent?.eventName || '比赛详情' }}</h3>
          <button
            class="close-btn"
            @click="closeEventDetail"
            aria-label="关闭详情"
          >
            &times;
          </button>
        </div>
        <div class="modal-body" v-if="currentEvent">
          <div class="event-detail">
            <!-- 比赛图片 -->
            <div class="event-detail-img">
              <img
                :src="currentEvent.eventImg || 'https://picsum.photos/800/400?random=' + getEventId(currentEvent)"
                :alt="currentEvent.eventName"
                loading="lazy"
                class="detail-img"
              >
            </div>
            <!-- 比赛信息 -->
            <ul class="event-detail-list">
              <li><strong>比赛ID：</strong>{{ getEventId(currentEvent) }}</li>
              <li><strong>比赛类别：</strong>{{ currentEvent.eventCategory }}</li>
              <li><strong>比赛时间：</strong>{{ formatDate(currentEvent.eventTime) }}</li>
              <li><strong>比赛地点：</strong>{{ currentEvent.eventLocation }}</li>
              <li><strong>比赛简介：</strong>{{ currentEvent.eventDesc || '暂无简介' }}</li>
              <li><strong>报名截止：</strong>{{ formatDate(currentEvent.registrationDeadline || currentEvent.eventTime) }}</li>
              <li><strong>参赛人数：</strong>{{ currentEvent.participantCount || 0 }} / {{ currentEvent.maxParticipants || '不限' }}</li>
              <li><strong>比赛费用：</strong>{{ currentEvent.price === 0 ? '免费' : currentEvent.price ? `¥${currentEvent.price}` : '暂无信息' }}</li>
            </ul>
          </div>
        </div>
        <div class="modal-footer">
          <button class="btn-close" @click="closeEventDetail">关闭</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue';
import EventList from './EventList.vue';
import RegisteredList from './RegisteredList.vue';
import MyScores from './MyScores.vue'; // 新增导入
import { request } from '@/utils/request';

// 定义 Event 类型
interface Event {
  eventId?: number;
  eventID?: string;
  eventName: string;
  eventTime: string;
  eventDesc: string;
  eventLocation: string;
  eventImg?: string;
  eventCategory: string;
  price: number;
  isFeatured: boolean;
  registrationDeadline?: string;
  participantCount?: number;
  maxParticipants?: number;
}

// 更新 Score 接口定义
interface Score {
  sId?: number;
  userId?: number;
  userName?: string;
  gameId?: number;
  eventId?: number;
  scheId?: number;
  rankId?: number;
  isPromoted?: number;
  sDistance?: number;
  sScore?: number;
  sTimeValue?: number;
  sType?: number;
  createTime?: string;
  updateTime?: string;
  // 可能需要从关联表中获取的字段
  eventName?: string;
  gameName?: string;
}

// 定义 API 响应基础类型
interface BaseApiResponse {
  success: boolean;
  message?: string;
  events?: unknown;
  event?: unknown;
  data?: unknown;
  scores?: unknown;
}

// 定义可能的响应数据形状
interface RawEventData {
  eventId?: number;
  eventID?: string;
  eventName?: unknown;
  eventTime?: unknown;
  eventDesc?: unknown;
  eventLocation?: unknown;
  eventImg?: unknown;
  eventCategory?: unknown;
  price?: unknown;
  isFeatured?: unknown;
  registrationDeadline?: unknown;
  participantCount?: unknown;
  maxParticipants?: unknown;
}

// 状态管理
const activeTab = ref<'all' | 'registered' | 'scores'>('all'); // 新增 scores 类型
const loadingTabs = ref(false);
const selectedCategory = ref('');
const searchKeyword = ref('');

// 全部比赛状态
const events = ref<Event[]>([]);
const loadingEvents = ref(false);
const errorEvents = ref('');

// 已报名比赛状态
const registeredEvents = ref<Event[]>([]);
const loadingRegistered = ref(false);
const errorRegistered = ref('');

// 新增：我的成绩状态
const scores = ref<Score[]>([]);
const loadingScores = ref(false);
const errorScores = ref('');


// 修复 Set 类型问题
const registeredEventIds = computed(() => {
  const ids = registeredEvents.value.map(event => getEventId(event));
  return new Set<string | number>(ids);
});

// 详情弹窗状态
const showEventDetail = ref(false);
const currentEvent = ref<Event | null>(null);
const isDetailLoading = ref(false);

// 统一获取事件ID的函数
const getEventId = (event: Event): string => {
  return String(event.eventID || event.eventId || '');
};

// 监听筛选条件变化
watch([selectedCategory, searchKeyword], () => {
  if (activeTab.value === 'all') {
    fetchEvents();
  }
});

// 初始化加载
onMounted(() => {
  fetchRegisteredEvents().then(() => {
    fetchEvents();
  });
});

// 标签切换处理
const handleTabChange = (tab: 'all' | 'registered' | 'scores') => {
  if (activeTab.value === tab) return;
  loadingTabs.value = true;
  activeTab.value = tab;

  if (tab === 'registered') {
    fetchRegisteredEvents().finally(() => {
      loadingTabs.value = false;
    });
  } else if (tab === 'scores') {
    fetchMyScores().finally(() => {
      loadingTabs.value = false;
    });
  } else {
    fetchEvents().finally(() => {
      loadingTabs.value = false;
    });
  }
};

/**
 * 新增：获取我的成绩
 */
const fetchMyScores = async () => {
  if (loadingScores.value) return;
  loadingScores.value = true;
  errorScores.value = '';

  try {
    const response = await request.get<BaseApiResponse>('/score/myScores');
    if (response.success) {
      let scoresData: Score[] = [];

      // 尝试从不同的字段获取数据并转换为 Score[]
      if (response.scores && Array.isArray(response.scores)) {
        scoresData = extractScoresFromArray(response.scores);
      } else if (response.data && Array.isArray(response.data)) {
        scoresData = extractScoresFromArray(response.data);
      } else if (Array.isArray(response)) {
        scoresData = extractScoresFromArray(response);
      }

      scores.value = scoresData;
    } else {
      errorScores.value = response.message || '获取成绩列表失败';
      if (response.message?.includes('未登录')) {
        localStorage.removeItem('token');
        localStorage.removeItem('userId');
        window.location.href = '/Login';
      }
    }
  } catch (err: unknown) {
    console.error('获取成绩列表失败:', err);
    const error = err as Error;
    errorScores.value = error.message?.includes('Network Error')
      ? '网络异常，请检查网络连接'
      : '服务器错误，获取成绩列表失败';
  } finally {
    loadingScores.value = false;
  }
};

/**
 * 新增：提取成绩数据
 */
const extractScoresFromArray = (data: unknown[]): Score[] => {
  return data
    .filter(item => isRawScoreData(item))
    .map(item => {
      const rawData = item as Record<string, unknown>;
      return {
        sId: Number(rawData.sid) || undefined,
        userId: Number(rawData.userId) || undefined,
        userName: String(rawData.userName || ''),
        gameId: Number(rawData.gameId) || undefined,
        eventId: Number(rawData.eventId) || undefined,
        scheId: Number(rawData.scheId) || undefined,
        rankId: Number(rawData.rankId) || undefined,
        isPromoted: Number(rawData.isPromoted) || 0,
        sDistance: Number(rawData.sdistance) || undefined,
        sScore: Number(rawData.sscore) || undefined,
        sTimeValue: Number(rawData.stimeValue) || undefined,
        sType: Number(rawData.stype) || undefined,
        createTime: String(rawData.ctime || ''),
        updateTime: String(rawData.utime || rawData.ctime || ''),
        // 如果有从关联表获取的字段
        eventName: String(rawData.eventName || `项目 ${rawData.eventId}`)
      };
    });
};
/**
 * 新增：检查是否为原始成绩数据的类型守卫
 */
const isRawScoreData = (data: unknown): boolean => {
  if (typeof data !== 'object' || data === null) return false;
  return true; // 根据实际数据结构调整
};

/**
 * 获取全部比赛列表
 */
const fetchEvents = async () => {
  if (loadingEvents.value) return;
  loadingEvents.value = true;
  errorEvents.value = '';

  try {
    let response: BaseApiResponse;

    // 如果有类别筛选，使用专门的类别API
    if (selectedCategory.value) {
      response = await request.get<BaseApiResponse>('/event/ByCategory', {
        params: {
          category: selectedCategory.value
        }
      });
    } else {
      // 否则获取全部比赛
      response = await request.get<BaseApiResponse>('/event/getListAll');
    }

    if (response.success) {
      let eventsData: Event[] = [];

      // 尝试从不同的字段获取数据并转换为 Event[]
      if (response.events && Array.isArray(response.events)) {
        eventsData = extractEventsFromArray(response.events);
      } else if (response.data && Array.isArray(response.data)) {
        eventsData = extractEventsFromArray(response.data);
      } else if (Array.isArray(response)) {
        eventsData = extractEventsFromArray(response);
      }

      // 前端关键词筛选
      if (searchKeyword.value.trim()) {
        const keyword = searchKeyword.value.trim().toLowerCase();
        eventsData = eventsData.filter(event =>
          event.eventName.toLowerCase().includes(keyword) ||
          (event.eventDesc && event.eventDesc.toLowerCase().includes(keyword)) ||
          (event.eventLocation && event.eventLocation.toLowerCase().includes(keyword))
        );
      }

      events.value = eventsData;
    } else {
      errorEvents.value = response.message || '获取比赛列表失败';
      if (response.message?.includes('未登录')) {
        localStorage.removeItem('token');
        localStorage.removeItem('userId');
        window.location.href = '/Login';
      }
    }
  } catch (err: unknown) {
    console.error('获取全部比赛失败:', err);
    const error = err as Error;
    errorEvents.value = error.message?.includes('Network Error')
      ? '网络异常，请检查网络连接'
      : '服务器错误，获取比赛列表失败';
  } finally {
    loadingEvents.value = false;
  }
};

/**
 * 获取已报名比赛列表
 */
const fetchRegisteredEvents = async () => {
  if (loadingRegistered.value) return;
  loadingRegistered.value = true;
  errorRegistered.value = '';

  try {
    const userId = localStorage.getItem('userId');
    if (!userId) {
      errorRegistered.value = '未检测到用户信息，请重新登录';
      window.location.href = '/Login';
      return;
    }

    const response = await request.get<BaseApiResponse>('/event/user');

    if (response.success) {
      let registeredData: Event[] = [];

      // 尝试从不同的字段获取数据并转换为 Event[]
      if (response.events && Array.isArray(response.events)) {
        registeredData = extractEventsFromArray(response.events);
      } else if (response.data && Array.isArray(response.data)) {
        registeredData = extractEventsFromArray(response.data);
      } else if (Array.isArray(response)) {
        registeredData = extractEventsFromArray(response);
      }

      registeredEvents.value = registeredData;
    } else {
      errorRegistered.value = response.message || '获取报名记录失败';
      if (response.message?.includes('未登录')) {
        localStorage.removeItem('token');
        localStorage.removeItem('userId');
        window.location.href = '/Login';
      }
    }
  } catch (err: unknown) {
    console.error('获取报名记录失败:', err);
    const error = err as Error;
    errorRegistered.value = error.message?.includes('Network Error')
      ? '网络异常，请检查网络连接'
      : '服务器错误，获取报名记录失败';
  } finally {
    loadingRegistered.value = false;
  }
};

// 🎯 修复：移除所有 any 类型，使用安全的类型转换
const extractEventsFromArray = (data: unknown[]): Event[] => {
  return data
    .filter(item => isRawEventData(item))
    .map(item => {
      const rawData = item as RawEventData;
      return {
        eventId: rawData.eventId,
        eventID: rawData.eventID,
        eventName: String(rawData.eventName || ''),
        eventTime: String(rawData.eventTime || ''),
        eventDesc: String(rawData.eventDesc || ''),
        eventLocation: String(rawData.eventLocation || ''),
        eventImg: typeof rawData.eventImg === 'string' ? rawData.eventImg : undefined,
        eventCategory: String(rawData.eventCategory || ''),
        price: Number(rawData.price || 0),
        isFeatured: Boolean(rawData.isFeatured || false),
        registrationDeadline: typeof rawData.registrationDeadline === 'string' ? rawData.registrationDeadline : undefined,
        participantCount: typeof rawData.participantCount === 'number' ? rawData.participantCount : undefined,
        maxParticipants: typeof rawData.maxParticipants === 'number' ? rawData.maxParticipants : undefined
      };
    });
};

// 🎯 新增：检查是否为原始事件数据的类型守卫
const isRawEventData = (data: unknown): data is RawEventData => {
  if (typeof data !== 'object' || data === null) return false;

  const obj = data as Record<string, unknown>;
  return (
    'eventName' in obj &&
    'eventTime' in obj
  );
};

/**
 * 查看比赛详情
 */
const handleViewEventDetail = async (eventId: number) => {
  if (isDetailLoading.value || !eventId) return;
  isDetailLoading.value = true;
  showEventDetail.value = true;

  try {
    const response = await request.get<BaseApiResponse>('/event/detail', {
      params: { eventId: eventId.toString() }
    });

    if (response.success && (response.event || response.data)) {
      const eventData = response.event || response.data;
      if (eventData && isEvent(eventData)) {
        currentEvent.value = eventData as Event;
      } else {
        throw new Error('事件数据格式不正确');
      }
    } else {
      throw new Error(response.message || '获取详情失败');
    }
  } catch (err: unknown) {
    console.error('获取比赛详情失败:', err);
    const error = err as Error;
    currentEvent.value = null;
    alert(`获取详情失败：${error.message?.includes('Network Error') ? '网络异常' : '服务器错误'}`);
    closeEventDetail();
  } finally {
    isDetailLoading.value = false;
  }
};

// 类型守卫：检查对象是否为 Event 类型
const isEvent = (data: unknown): data is Event => {
  if (typeof data !== 'object' || data === null) return false;
  const event = data as Record<string, unknown>;
  return (
    typeof event.eventName === 'string' &&
    typeof event.eventTime === 'string' &&
    typeof event.eventDesc === 'string' &&
    typeof event.eventLocation === 'string' &&
    typeof event.eventCategory === 'string' &&
    typeof event.price === 'number' &&
    typeof event.isFeatured === 'boolean'
  );
};

/**
 * 报名比赛
 */
const isSubmitting = ref(false); // 🎯 新增：防止重复提交

const handleRegisterEvent = async (eventId: number) => {
  // 🎯 修复：防止重复提交
  if (isSubmitting.value) {
    console.log('正在提交中，请勿重复操作');
    return;
  }

  if (!confirm('确定要报名此比赛吗？报名后请按时参赛～')) return;

  isSubmitting.value = true; // 🎯 开始提交

  try {
    const userId = localStorage.getItem('userId');
    if (!userId) {
      alert('未检测到用户信息，请重新登录');
      window.location.href = '/Login';
      return;
    }

    console.log('报名比赛:', { eventId, userId });

    if (!eventId || eventId === 0) {
      alert('无效的比赛ID');
      return;
    }

    // 🎯 修复：使用正确的错误处理类型
    const response = await request.post<BaseApiResponse>('/event/register', {
      eventId: eventId.toString()
    }).catch((error: unknown) => {
      // 🎯 使用类型安全的错误处理
      if (isAxiosErrorWithResponse(error)) {
        const responseData = error.response?.data as BaseApiResponse | undefined;
        if (responseData?.success) {
          console.log('业务逻辑成功，但HTTP状态码错误:', responseData);
          return responseData; // 返回业务成功的数据
        }
      }
      throw error; // 其他错误继续抛出
    });

    console.log('报名响应:', response);

    if (response.success) {
      alert('报名成功！已添加到已报名列表～');
      fetchEvents();
      fetchRegisteredEvents();
    } else {
      alert(`报名失败：${response.message || '未知错误'}`);
      if (response.message?.includes('未登录')) {
        localStorage.removeItem('token');
        localStorage.removeItem('userId');
        window.location.href = '/Login';
      }
    }
  } catch (err: unknown) {
    console.error('报名比赛失败:', err);

    // 🎯 修复：类型安全的错误处理
    let errorMessage = '报名失败，请稍后重试';

    if (isAxiosErrorWithResponse(err)) {
      const responseData = err.response?.data as BaseApiResponse | undefined;

      // 检查是否是业务逻辑成功但HTTP错误的情况
      if (responseData?.success) {
        console.log('业务逻辑成功，忽略HTTP错误');
        alert('报名成功！已添加到已报名列表～');
        fetchEvents();
        fetchRegisteredEvents();
        return;
      }

      errorMessage = responseData?.message || err.message || errorMessage;
    } else if (err instanceof Error) {
      errorMessage = err.message || errorMessage;
    }

    alert(errorMessage);
  } finally {
    // 🎯 修复：无论成功失败，都要重置提交状态
    isSubmitting.value = false;
  }
};
/**
 * 取消报名
 */
const handleCancelRegistration = async (eventId: number) => {
  if (!confirm('确定要取消此比赛的报名吗？取消后将无法恢复～')) return;

  try {
    const userId = localStorage.getItem('userId');
    if (!userId) {
      alert('未检测到用户信息，请重新登录');
      window.location.href = '/Login';
      return;
    }

    // 🎯 修复：类型安全的错误处理
    const response = await request.post<BaseApiResponse>('/event/cancel', {
      eventId: eventId.toString()
    }).catch((error: unknown) => {
      if (isAxiosErrorWithResponse(error)) {
        const responseData = error.response?.data as BaseApiResponse | undefined;
        if (responseData?.success) {
          console.log('取消报名业务逻辑成功，但HTTP状态码错误:', responseData);
          return responseData;
        }
      }
      throw error;
    });

    if (response.success) {
      alert('取消报名成功！已从已报名列表移除～');
      fetchEvents();
      fetchRegisteredEvents();
    } else {
      alert(`取消失败：${response.message || '未知错误'}`);
      if (response.message?.includes('未登录')) {
        localStorage.removeItem('token');
        localStorage.removeItem('userId');
        window.location.href = '/Login';
      }
    }
  } catch (err: unknown) {
    console.error('取消报名失败:', err);

    let errorMessage = '取消报名失败，请稍后重试';

    if (isAxiosErrorWithResponse(err)) {
      const responseData = err.response?.data as BaseApiResponse | undefined;

      if (responseData?.success) {
        console.log('取消报名业务逻辑成功，忽略HTTP错误');
        alert('取消报名成功！已从已报名列表移除～');
        fetchEvents();
        fetchRegisteredEvents();
        return;
      }

      errorMessage = responseData?.message || err.message || errorMessage;
    } else if (err instanceof Error) {
      errorMessage = err.message || errorMessage;
    }

    alert(errorMessage);
  }
};

// 🎯 新增：Axios 错误类型守卫
interface AxiosErrorWithResponse extends Error {
  response?: {
    data: unknown;
    status: number;
    statusText: string;
    headers: unknown;
    config: unknown;
  };
  config?: unknown;
  code?: string;
}

const isAxiosErrorWithResponse = (error: unknown): error is AxiosErrorWithResponse => {
  if (!(error instanceof Error)) return false;
  const axiosError = error as AxiosErrorWithResponse;
  return axiosError.response !== undefined;
};

// 关闭详情弹窗
const closeEventDetail = () => {
  showEventDetail.value = false;
  setTimeout(() => {
    currentEvent.value = null;
  }, 300);
};

// 格式化日期
const formatDate = (dateString: string) => {
  if (!dateString) return '暂无数据';
  const date = new Date(dateString);
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  });
};
</script>

<style scoped>
.events-page {
  width: 100%;
  height: 100%;
}
.user-scores-info {
  margin-bottom: 20px;
  padding: 20px;
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.user-scores-info h3 {
  margin: 0 0 10px 0;
  color: #2c3e50;
  font-size: 1.5rem;
}
.page-subtitle {
  text-align: center;
  font-size: 2rem;
  font-weight: bold;
  margin: 0 0 20px 0;
  color: #2c3e50;
  background: linear-gradient(to right, #31B310, #3498db);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.tabs-container {
  background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
  border-radius: 15px;
  padding: 30px;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
  height: 100%;
  display: flex;
  flex-direction: column;
}

/* 标签页样式 */
.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 24px;
  border-bottom: 1px solid #f3f4f6;
}

.tab-btn {
  padding: 12px 24px;
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  font-size: 16px;
  color: #6b7280;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
}

.tab-btn.active {
  color: #31B310;
  border-bottom-color: #31B310;
  background: linear-gradient(135deg, rgba(49, 179, 16, 0.1) 0%, rgba(52, 152, 219, 0.1) 100%);
  border-radius: 8px 8px 0 0;
}

.tab-btn:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* 筛选栏样式 */
.filter-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  flex-wrap: wrap;
  gap: 16px;
  padding: 20px;
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.category-select {
  padding: 10px 15px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  font-size: 14px;
  color: #1f2937;
  background-color: #fff;
  transition: all 0.3s ease;
}

.category-select:focus {
  outline: none;
  border-color: #31B310;
  box-shadow: 0 0 0 3px rgba(49, 179, 16, 0.1);
}

.search-box {
  display: flex;
  align-items: center;
  max-width: 400px;
  width: 100%;
}

.search-box input {
  flex: 1;
  padding: 10px 15px;
  border: 1px solid #d1d5db;
  border-right: none;
  border-radius: 8px 0 0 8px;
  font-size: 14px;
  outline: none;
  transition: border-color 0.3s ease;
}

.search-box input:focus {
  border-color: #31B310;
}

.search-btn {
  padding: 10px 20px;
  background: linear-gradient(to right, #31B310, #2a990e);
  color: white;
  border: none;
  border-radius: 0 8px 8px 0;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.search-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}

.search-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* 内容区域样式 */
.tab-content {
  flex: 1;
  overflow-y: auto;
}

.tab-panel {
  animation: fadeIn 0.3s ease-in-out;
}

.user-registered-info {
  margin-bottom: 20px;
  padding: 20px;
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.user-registered-info h3 {
  margin: 0 0 10px 0;
  color: #2c3e50;
  font-size: 1.5rem;
}

.no-data {
  color: #6c757d;
  text-align: center;
  padding: 20px;
  font-size: 1.1rem;
}

/* 加载指示器样式 */
.tab-loading, .search-loading {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(107, 114, 128, 0.3);
  border-radius: 50%;
  border-top-color: #6b7280;
  animation: spin 1s linear infinite;
  display: inline-block;
}

/* 弹窗样式 */
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}

.modal {
  background-color: white;
  border-radius: 15px;
  width: 100%;
  max-width: 800px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
  animation: modalSlideIn 0.3s ease-out;
}

@keyframes modalSlideIn {
  from {
    opacity: 0;
    transform: translateY(-30px) scale(0.9);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.modal-header {
  padding: 20px;
  border-bottom: 1px solid #f3f4f6;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: linear-gradient(135deg, #31B310, #3498db);
  border-radius: 15px 15px 0 0;
}

.modal-title {
  margin: 0;
  font-size: 1.5rem;
  color: white;
  font-weight: 600;
}

.close-btn {
  background: transparent;
  border: none;
  font-size: 28px;
  cursor: pointer;
  color: white;
  transition: color 0.3s ease;
  padding: 0 8px;
  line-height: 1;
}

.close-btn:hover {
  color: #f0f0f0;
  transform: scale(1.1);
}

.modal-body {
  padding: 30px;
  overflow-y: auto;
  flex: 1;
}

.event-detail {
  display: flex;
  flex-direction: column;
  gap: 25px;
}

.event-detail-img {
  width: 100%;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.detail-img {
  width: 100%;
  height: auto;
  object-fit: cover;
  display: block;
}

.event-detail-list {
  list-style: none;
  padding: 0;
  margin: 0;
  background: #f8f9fa;
  border-radius: 10px;
  padding: 20px;
}

.event-detail-list li {
  margin-bottom: 15px;
  line-height: 1.6;
  color: #4b5563;
  padding: 8px 0;
  border-bottom: 1px solid #e5e7eb;
}

.event-detail-list li:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

.event-detail-list strong {
  color: #2c3e50;
  min-width: 100px;
  display: inline-block;
  font-weight: 600;
}

.modal-footer {
  padding: 20px;
  border-top: 1px solid #f3f4f6;
  display: flex;
  justify-content: flex-end;
  background: #f8f9fa;
  border-radius: 0 0 15px 15px;
}

.btn-close {
  padding: 10px 24px;
  background: linear-gradient(to right, #31B310, #2a990e);
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s ease;
  font-size: 16px;
  font-weight: 500;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.btn-close:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}

/* 动画 */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* 响应式调整 */
@media (min-width: 768px) {
  .event-detail {
    flex-direction: row;
  }
  .event-detail-img {
    width: 40%;
  }
  .event-detail-list {
    width: 60%;
  }
}

@media (max-width: 768px) {
  .tabs-container {
    padding: 20px;
  }

  .filter-bar {
    flex-direction: column;
    align-items: stretch;
  }

  .search-box {
    max-width: none;
  }

  .modal {
    margin: 10px;
  }
}
</style>
